/*
 * Copyright 2008 Zoundry LLC, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package test.org.zoundry.gaedt.core;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import junit.framework.TestCase;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.zoundry.gaedt.core.util.ZGaeCloser;
import org.zoundry.gaedt.core.util.ZGaeFileUtil;
import org.zoundry.gaedt.core.util.ZGaeUTF8Util;

/**
 * A base class for all GAE test cases.
 */
public class ZGaeTestCase extends TestCase
{
    /**
     * Creates a temp directory.  The caller is responsible for deleting
     * the resulting temporary directory.
     *
     * @throws Exception
     */
    protected File createTempDir() throws Exception
    {
        File tempFile = File.createTempFile("_zgae", ".dir");
        tempFile.delete();
        if (tempFile.mkdir())
            return tempFile;
        else
            throw new Exception("Failed to create temp directory.");
    }

    /**
     * Creates a temporary file out of the content in the given input stream.
     *
     * @param aContent
     * @throws FileNotFoundException
     * @throws IOException
     */
    protected File createTempFile(InputStream aContent) throws Exception
    {
        try
        {
            File tmpFile = createTempFile();
            FileOutputStream oStream = new FileOutputStream(tmpFile);
            try
            {
                ZGaeFileUtil.copy(aContent, oStream);
            }
            finally
            {
                ZGaeCloser.close(oStream);
            }
            assertFileExists(tmpFile);
            return tmpFile;
        }
        finally
        {
            ZGaeCloser.close(aContent);
        }
    }

    /**
     * Creates a temporary file.
     *
     * @throws Exception
     */
    protected File createTempFile() throws Exception
    {
        File tmpFile = File.createTempFile("_zgae", ".bin");
        tmpFile.deleteOnExit();
        return tmpFile;
    }

    /**
     * Creates the test project within which the application model
     * test will take place.
     *
     * @param aProjectName
     * @throws Exception
     */
    protected IProject createTestProject(String aProjectName) throws Exception
    {
        IProject newProjectHandle = ResourcesPlugin.getWorkspace().getRoot().getProject(aProjectName);
        newProjectHandle.create(null);
        newProjectHandle.open(null);
        return newProjectHandle;
    }

    /**
     * Gets the project with the given name or creates it if it does
     * not already exist.
     *
     * @param aProjectName
     * @throws Exception
     */
    protected IProject getOrCreateTestProject(String aProjectName) throws Exception
    {
        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(aProjectName);
        if (project.exists())
            return project;
        else
            return createTestProject(aProjectName);
    }

    /**
     * Creates a test file in the given project at the given path with the
     * given content.
     *
     * @param aProject
     * @param aFilePath
     * @param aContent
     */
    protected IFile createTestFile(IProject aProject, IPath aFilePath, String aContent) throws Exception
    {
        IFile file = aProject.getFile(aFilePath);
        assertFalse("File at " + aFilePath + " already exists.", file.exists());
        file.create(ZGaeUTF8Util.getInputStream(aContent), true, null);
        return file;
    }

    /**
     * Asserts that the actual value is equal to the data in the given
     * expected resource.
     *
     * @param aExpectedResourceUrl
     * @param aActualValue
     */
    protected void assertEquals(URL aExpectedResourceUrl, String aActualValue) throws Exception
    {
        String expectedValue = toString(aExpectedResourceUrl);
        super.assertEquals(expectedValue, aActualValue);
    }

    /**
     * Reads the content at the given URL into a String.
     *
     * @param aExpectedResourceUrl
     */
    protected String toString(URL aExpectedResourceUrl) throws Exception
    {
        InputStream iStream = aExpectedResourceUrl.openStream();
        try
        {
            return toString(iStream);
        }
        finally
        {
            ZGaeCloser.close(iStream);
        }
    }

    /**
     * Reads the content at the given URL into a String.
     *
     * @param aExpectedResource
     */
    protected String toString(InputStream aExpectedResource) throws Exception
    {
        StringBuffer buffer = new StringBuffer();
        synchronized (buffer)
        {
            BufferedReader reader = new BufferedReader(new InputStreamReader(aExpectedResource));
            String line = null;
            while ( (line = reader.readLine()) != null )
            {
                buffer.append(line);
                buffer.append("\n");
            }
        }
        return buffer.toString();
    }

    /**
     * Asserts that the given file exists.
     *
     * @param aFile
     * @throws Exception
     */
    protected void assertFileExists(File aFile) throws Exception
    {
        assertTrue("File does not exist.", aFile != null && aFile.exists());
    }
}
